import configparser
import json
import os
import sys
import traceback
from concurrent.futures import ThreadPoolExecutor

import requests
from flask import Flask, request, Response
from loguru import logger

from hlj_engine_server.hlj_worker import IWorker
from hlj_engine_server.rabbitmq_client import RabbitMQClient


class HLJEngineServer:
    def __init__(self, worker: IWorker, conf_path='server.ini'):
        self.worker = worker
        self.conf = configparser.ConfigParser()
        self.conf.read(conf_path)
        self.server_port = int(self.conf.get('server', 'port'))
        self.server_log_level = str(self.conf.get('server', 'log_level'))
        self.server_mq_url = str(self.conf.get('server', 'mq_url'))
        self.server_mq_out = str(self.conf.get('server', 'mq_out'))
        self.custom_endpoint = str(self.conf.get('server', 'custom_endpoint', fallback="/custom_endpoint")).strip()
        try:
            self.engine_version = str(self.conf.get('server', 'engine_version'))
        except Exception as e:
            logger.warning("No [engine_version] in server.ini")
            self.engine_version = None

        tmp_value = os.environ.get("MQ_URL")
        if tmp_value:
            self.server_mq_url = str(tmp_value)

        tmp_value = os.environ.get("LOG_LEVEL")
        if tmp_value:
            self.server_log_level = str(tmp_value)

        self.rabbitmq_client = RabbitMQClient(self.server_mq_url, self.server_mq_out)

        # set log level
        logger.remove()
        logger.add(sys.stdout, level=self.server_log_level)

    def run(self):
        app = Flask(__name__)

        # 创建一个大小为1的线程池
        executor = ThreadPoolExecutor(max_workers=1)

        @app.before_request
        def before_request():
            # 在flask启动后，设置werkzeug日志级别
            import logging
            log = logging.getLogger('werkzeug')
            log.setLevel(logging.ERROR)

        def run_core(input_data):
            sid = input_data.get('sid')
            # 处理
            try:
                result = self.worker.process(input_data)
                logger.debug(f'返回: {json.dumps(result)}')
                response_body = {
                    "sid": sid,
                    "code": 0,
                    "errMsg": None,
                    "result": result,
                    "engine_version": self.engine_version
                }
            except Exception as e:
                logger.error(traceback.format_exc())
                response_body = {
                    "sid": sid,
                    "code": -1,
                    "errMsg": str(e),
                    "traceback": traceback.format_exc(),
                    "engine_version": self.engine_version
                }

            # 回调
            try:
                if "callback" in input_data:
                    for callback_item in input_data['callback']:
                        try:
                            type = callback_item.get('type', None)
                            out = callback_item.get('out', None)
                            if type == "http":
                                requests.post(out, headers={'Content-Type': 'application/json'}, data=json.dumps(response_body))
                            elif type == "rabbitmq":
                                self.rabbitmq_client.publish_msg(out, response_body)
                        except Exception:
                            logger.error(traceback.format_exc())
            except Exception:
                logger.error(traceback.format_exc())
            finally:
                return response_body

        @app.route('/hlj/engine/v2/api/run', methods=['POST'])
        def run():
            # 序列化body
            try:
                input_data = json.loads(request.get_data())
                logger.debug(f'请求: {json.dumps(input_data)}')
            except Exception:
                return {
                    "code": 9001,
                    "errMsg": "请求体json解析异常",
                }

            return run_core(input_data)

        @app.route('/hlj/engine/v2/api/run/async', methods=['POST'])
        def run_async():
            # 序列化body
            try:
                input_data = json.loads(request.get_data())
                logger.debug(f'请求: {json.dumps(input_data)}')
            except Exception:
                return {
                    "code": 9001,
                    "errMsg": "请求体json解析异常",
                }
            # 将任务提交到线程池队列中
            executor.submit(run_core, input_data)
            return Response(status=202)

        @app.route('/hlj/engine/v2/api/run/healthcheck', methods=['GET'])
        def healthcheck():
            return {"code": 0}

        @app.route(self.custom_endpoint, methods=['POST'])
        def gateway_like_api():
            # 获取 URL 查询参数 Sync
            sync_param = request.args.get('Sync', 'false')  # 默认值为 'false'
            if sync_param == 'true':
                return run()
            else:
                return run_async()

        app.run(host='0.0.0.0', port=self.server_port)


if __name__ == '__main__':
    class WorkerMock(IWorker):
        def __init__(self):
            # 加载配置文件，可以用来初始化引擎
            logger.debug("构造引擎实例")

        def process(self, data):
            logger.debug("引擎处理")
            return {"input": data}


    server = HLJEngineServer(WorkerMock())
    server.run()
